package com.zb.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.*;
import com.zb.exception.SMSException;
import com.zb.mapper.ZjUserMapper;
import com.zb.mobile.UserMobileInfoVo;
import com.zb.result.PageUtil;
import com.zb.secure.BCryptUtil;
import com.zb.service.*;
import com.zb.util.MobileUserSmsUtil;
import com.zb.utils.RandomUtil;
import com.zb.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-08-08
 */
@Service
public class ZjUserServiceImpl extends ServiceImpl<ZjUserMapper, ZjUser> implements ZjUserService {
    @Resource
    private ZjUserMapper userMapper;
    @Resource
    private ZjUserSetService userSetService;
    @Resource
    private ZjUserContactService userContactService;
    @Resource
    private ZjUserLevelService userLevelService;

    // 新增用户
    @Override
    @Transactional
    public void save(AccounLoginInfo accountLoginInfo, UserVo userVo) {
        Assert.isTrue(null == userMapper.existByPhone(accountLoginInfo.getCustAccId(), userVo.getId(), userVo.getPhone()), "手机号已重复！", userVo.getPhone());
        if (StringUtils.isBlank(userVo.getCode())) {
            userVo.setCode(userSetService.getCodeById(accountLoginInfo.getCustAccId()) + RandomUtil.random16());
        }
        ZjUser user = new ZjUser();
        BeanUtils.copyProperties(userVo, user);
        if (null != user.getId()) {
            this.updateById(user);
        } else {
            user.setId(IdWorker.getId());
            user.setCustAccId(accountLoginInfo.getCustAccId());
            user.setSalt(BCryptUtil.generatorSalt());
            user.setAccount("ZB" + BCryptUtil.generatorSalt().substring(10, 20));
            user.setPassword(BCryptUtil.encryPassword(SaSecureUtil.md5(user.getPhone().substring(5)), user.getSalt()));
            user.setMoney(new BigDecimal("0.0"));
            user.setNickname(userVo.getName() + user.getPhone().substring(7));
            user.setAvatar("");
            user.setSelectKnowledgeAuthor(userSetService.getSelectKnowledgeAuthor(accountLoginInfo.getCustAccId()));
            user.setLevelId(null == user.getLevelId()? 0L : user.getLevelId());
            user.setLevel(null == user.getLevel()? "" : userVo.getLevel());
            user.setUserTypeId(null == user.getUserTypeId()? 0 : userVo.getUserTypeId());
            user.setUserType(null == user.getUserType()? "" : user.getUserType());
            user.setCreateEmpId(accountLoginInfo.getId());
            user.setUpdateEmpId(accountLoginInfo.getId());
            this.save(user);
            userContactService.saveMainContact(accountLoginInfo.getCustAccId(), user.getId(), userVo);
        }
    }

    // 新增用户
    @Override
    public Long save(AccounLoginInfo loginInfo, UserInfo userInfo) {
        Long id = userMapper.getIdByPhone(loginInfo.getCustAccId(), userInfo.getPhone());
        if (null != id) {
            return id;
        }
        ZjUser user = new ZjUser();
        user.setId(IdWorker.getId());
        user.setCustAccId(loginInfo.getCustAccId());
        user.setPhone(userInfo.getPhone());
        user.setAccount("ZB" + BCryptUtil.generatorSalt().substring(10, 20));
        user.setSalt(BCryptUtil.generatorSalt());
        user.setPassword(BCryptUtil.encryPassword(SaSecureUtil.md5(user.getPhone().substring(5)), user.getSalt()));
        user.setCode(userSetService.getCodeById(loginInfo.getCustAccId()) + RandomUtil.random16());
        user.setName(userInfo.getName());
        user.setNickname(user.getName() + user.getPhone().substring(7));
        user.setStatus(0);
        user.setAvatar("");
        user.setMoney(new BigDecimal("0.0"));
        user.setLevelId(userSetService.getLevelIdById(loginInfo.getCustAccId()));
        user.setLevel(user.getLevelId() == 0? "" : userLevelService.getNameById(user.getLevelId()));
        user.setUserTypeId(0L);
        user.setUserType("");
        user.setSelectKnowledgeAuthor(userSetService.getSelectKnowledgeAuthor(loginInfo.getCustAccId()));
        user.setCreateEmpId(loginInfo.getId());
        user.setUpdateEmpId(loginInfo.getId());
        this.save(user);
        userContactService.saveMainContact(loginInfo.getCustAccId(), user.getId(), userInfo);
        return user.getId();
    }

    // 新增用户
    @Override
    public ZjUser save(Long custAccId, String phone, String password) {
        ZjUser user = userMapper.getByPhone(custAccId, phone);
        if (null != user) {
            return user;
        }
        user = new ZjUser();
        user.setId(IdWorker.getId());
        user.setCustAccId(custAccId);
        user.setPhone(phone);
        user.setAccount("ZB" + BCryptUtil.generatorSalt().substring(10, 20));
        user.setSalt(BCryptUtil.generatorSalt());
        user.setPassword(BCryptUtil.encryPassword(StringUtils.isNotBlank(password)? password : SaSecureUtil.md5(user.getPhone().substring(5)), user.getSalt()));
        user.setCode(userSetService.getCodeById(custAccId) + RandomUtil.random16());
        user.setName(user.getPhone().substring(5));
        user.setNickname(user.getName() + user.getPhone().substring(7));
        user.setStatus(0);
        user.setAvatar("");
        user.setMoney(new BigDecimal("0.0"));
        user.setLevelId(userSetService.getLevelIdById(custAccId));
        user.setLevel(user.getLevelId() == 0? "" : userLevelService.getNameById(user.getLevelId()));
        user.setUserTypeId(0L);
        user.setUserType("");
        user.setSelectKnowledgeAuthor(userSetService.getSelectKnowledgeAuthor(custAccId));
        user.setCreateEmpId(0L);
        user.setUpdateEmpId(0L);
        this.save(user);
        userContactService.saveMainContact(custAccId, user.getId(),
                new UserInfo()
                        .setName(user.getName())
                        .setPhone(user.getPhone())
                        .setProvince("")
                        .setCity("")
                        .setArea("")
                        .setTown("")
                        .setAddress("")
        );
        return user;
    }

    // 获取用户列表
    @Override
    public List<UserListVo> getList(Long custAccId, UserSelectVo selectVo) {
        return userMapper.getList(custAccId, selectVo);
    }

    // 获取用户列表总记录数
    @Override
    public long getListCount(Long custAccId, UserSelectVo selectVo) {
        return userMapper.getListCount(custAccId, selectVo);
    }

    // 获取用户账号信息
    @Override
    public UserAccountVo getUserAccount(Long id) {
        ZjUser user = this.getById(id);
        Assert.isTrue(null != user, "参数[" + id + "]的数据不存在！", null);
        UserAccountVo vo = new UserAccountVo();
        BeanUtils.copyProperties(user, vo);
        vo.setCreateTime(user.getGmtCreate());
        vo.setUpdateTime(user.getGmtUpdate());
        ZjUserContact contact = userContactService.getMainContactByUserId(id);
        if (null != contact) {
            vo.setEmail(contact.getEmail());
            vo.setProvince(contact.getProvince());
            vo.setCity(contact.getCity());
            vo.setArea(contact.getArea());
            vo.setTown(contact.getTown());
            vo.setAddress(contact.getAddress());
        }
        return vo;
    }

    // 批量更改用户状态
    @Override
    public void updateBatchStatusByIds(List<Long> idList, Integer status) {
        userMapper.updateBatchStatusByIds(idList, status);
    }

    // 查询用户级别是否存在
    @Override
    public List<String> existLevelTypeByUserLevelIds(List<Long> userLevelIdList) {
        return userMapper.existLevelTypeByUserLevelIds(userLevelIdList);
    }

    // 根据类型ID集合查询是否存在
    @Override
    public List<String> existTypeByTypeIds(List<Long> typeIdList) {
        return userMapper.existTypeByTypeIds(typeIdList);
    }

    // 分页获取用户下拉数据列表
    @Override
    public Map<String, Object> pageSelect(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        long count = userMapper.pageSelectCount(custAccId, selectVo);
        if (count <= 0) {
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, new ArrayList<>());
        }
        List<SelectEmpAddressVo> voList = userMapper.pageSelect(custAccId, selectVo);

//        List<Long> userIds = voList.stream().map(SelectResultVo::getId).toList();
//        List<ZjUserContact> userContacts = userContactService.getMainContactByUserIds(userIds);
//        voList.forEach(t -> {
//            ZjUserContact userContact = userContacts.stream().filter(contact -> Objects.equals(t.getId(), contact.getUserId())).findFirst().orElse(null);
//            if (null != userContact) {
//                t.setProvince(userContact.getProvince());
//                t.setCity(userContact.getCity());
//                t.setArea(userContact.getArea());
//                t.setTown(userContact.getTown());
//                t.setAddress(userContact.getAddress());
//            }
//        });
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, voList);
    }

    // 根据手机号查询
    @Override
    public ZjUser getByPhone(Long custAccId, String phone) {
        return userMapper.getByPhone(custAccId, phone);
    }

    // 根据登录账号查询
    @Override
    public ZjUser getByAccount(Long custAccId, String account) {
        return userMapper.getByAccount(custAccId, account);
    }

    // 校验手机号是否注册
    @Override
    public boolean isRegisterPhone(Long custAccId, String phone) {
        return null != userMapper.existByPhone(custAccId, null, phone);
    }

    // 根据用户更新最后登录时间
    @Override
    public void updatelastLoginTimeByLogin(Long id) {
        ZjUser user = new ZjUser();
        user.setId(id);
        user.setLastLoginTime(new Date());
        this.updateById(user);
    }

    // 登录页面的重置密码
    @Override
    public void logInRestPwd(Long custAccId, UserPasswordVo userPasswordVo) throws SMSException {
        if (userPasswordVo.getType() == 1) {
            Assert.isTrue(StringUtils.isNotBlank(userPasswordVo.getCode()), "验证码不能为空");
            MobileUserSmsUtil.checkUpdateVerificCode(userPasswordVo.getPhone(), userPasswordVo.getCode());
        }
        if (userPasswordVo.getType() == 2) {
            Assert.isTrue(StringUtils.isNotBlank(userPasswordVo.getOldPassword()), "旧密码不能为空");
        }

        ZjUser oldUser = userMapper.getByPhone(custAccId, userPasswordVo.getPhone());
        Assert.isTrue(null != oldUser, "手机号["+ userPasswordVo.getPhone() +"]的用户未注册");
        if (userPasswordVo.getType() == 2) {
            String oldPwd = SaSecureUtil.md5(userPasswordVo.getOldPassword());
            Assert.isTrue(Objects.equals(oldUser.getPassword(), BCryptUtil.encryPassword(oldPwd, oldUser.getSalt())), "旧密码错误");
        }

        ZjUser user = new ZjUser();
        user.setId(oldUser.getId());
        user.setSalt(BCryptUtil.generatorSalt());
        user.setPassword(BCryptUtil.encryPassword(userPasswordVo.getNewPassword(), user.getSalt()));
        this.updateById(user);
    }

    // 修改密码
    @Override
    public void updatePwd(Long userId, UserPasswordVo userPasswordVo) throws SMSException {
        if (userPasswordVo.getType() == 1) {
            Assert.isTrue(StringUtils.isNotBlank(userPasswordVo.getCode()), "验证码不能为空");
            MobileUserSmsUtil.checkUpdateVerificCode(userPasswordVo.getPhone(), userPasswordVo.getCode());
        }
        if (userPasswordVo.getType() == 2) {
            Assert.isTrue(StringUtils.isNotBlank(userPasswordVo.getOldPassword()), "旧密码不能为空");
        }
        ZjUser oldUser = this.getById(userId);
        if (userPasswordVo.getType() == 1) {
            Assert.isTrue(Objects.equals(oldUser.getPhone(), userPasswordVo.getPhone()), "修改密码的手机号与系统注册的手机号不一致："+ userPasswordVo.getPhone());
        }
        if (userPasswordVo.getType() == 2) {
            Assert.isTrue(Objects.equals(oldUser.getPassword(), BCryptUtil.encryPassword(userPasswordVo.getOldPassword(), oldUser.getSalt())), "旧密码错误");
        }
        ZjUser user = new ZjUser();
        user.setId(oldUser.getId());
        user.setSalt(BCryptUtil.generatorSalt());
        user.setPassword(BCryptUtil.encryPassword(userPasswordVo.getNewPassword(), user.getSalt()));
        this.updateById(user);
    }

    // 查询是否已绑定手机号
    @Override
    public boolean isBindingPhone(Long userId) {
        ZjUser user = this.getById(userId);
        Assert.isTrue(null != user, "用户数据不存在");
        return StringUtils.isNotBlank(user.getPhone());
    }

    // 绑定手机号
    @Override
    public void bindingPhone(Long userId, String phone, String code) throws SMSException {
        ZjUser zjUser = this.getById(userId);
        MobileUserSmsUtil.checkUpdateVerificCode(zjUser.getPhone(), code);
        ZjUser user = new ZjUser();
        user.setId(userId);
        user.setPhone(phone);
        this.updateById(user);
    }

    // 新增/修改联系人地址
    @Override
    @Transactional
    public void saveUserContactAddress(AccounLoginInfo logintInfo, UserContactVo userContactVo) {
        Assert.isTrue(null == userContactService.existByPhone(logintInfo.getId(), userContactVo.getId(), userContactVo.getPhone()), "联系人已存在");
        ZjUserContact mainContactUser = userContactService.getMainContactByUserId(logintInfo.getId());
        if (!userContactVo.getMainContact() && Objects.equals(userContactVo.getId(), mainContactUser.getId())) {
            Assert.isTrue(false, "必须指定一个默认联系人与地址");
        }

        List<ZjUserContact> updates = new ArrayList<>();
        if (userContactVo.getMainContact() && !Objects.equals(userContactVo.getId(), mainContactUser.getId())) {
            ZjUserContact contact = new ZjUserContact();
            contact.setId(mainContactUser.getId());
            contact.setMainContact(false);
            updates.add(contact);
        }
        ZjUserContact contact = new ZjUserContact();
        BeanUtil.copyProperties(userContactVo, contact);
        if (null != contact.getId()) {
            updates.add(contact);
        } else {
            contact.setId(IdWorker.getId());
            contact.setCustAccId(logintInfo.getCustAccId());
            contact.setUserId(logintInfo.getId());
            contact.setEmail(null == contact.getEmail()? "" : contact.getEmail());
            userContactService.save(contact);
        }
        if (CollectionUtil.isNotEmpty(updates)) userContactService.updateBatchById(updates);
    }

    //
    @Override
    public void updateMobileUserInfo(Long userId, UserMobileInfoVo userMobileInfoVo) {
       ZjUser user = new ZjUser();
       BeanUtil.copyProperties(userMobileInfoVo, user);
       user.setId(userId);
       this.updateById(user);
    }

    // 更新客户知识库查看权限
    @Override
    public void updateSelectKnowledgeAuthor(Long id, boolean selectKnowledgeAuthor) {
        ZjUser user = new ZjUser();
        user.setId(id);
        user.setSelectKnowledgeAuthor(selectKnowledgeAuthor);
        this.updateById(user);
    }

    // 获取出入库客户下拉数据列表
    @Override
    public Map<String, Object> getStoreUserPageSelect(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        List<SelectEmpAddressVo> empAddressVos = userMapper.getStoreUserPageSelect(custAccId, selectVo);
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), userMapper.getStoreUserPageSelectCount(custAccId, selectVo), empAddressVos);
    }

    // 获取出库收货客户信息
    @Override
    public Map<String, Object> getOutStoreUser(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        List<SelectEmpAddressVo> empAddressVos = userMapper.getOutStoreUser(custAccId, selectVo);
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), userMapper.getOutStoreUserCount(custAccId, selectVo), empAddressVos);
    }

    // 获取报单客户下拉数据列表
    @Override
    public Map<String, Object> getOrderUserSelect(Long custAccId, UserSelectSearch search) {
        PageUtil.setSelectPageLimit(search);
        long count = userMapper.getOrderUserSelectCount(custAccId, search);
        if (count <= 0) {
            return PageUtil.pageList(search.getPage(), search.getLimit(), count, new ArrayList<>());
        }
        List<SelectEmpAddressVo> voList = userMapper.getOrderUserSelect(custAccId, search);
        return PageUtil.pageList(search.getPage(), search.getLimit(), count, voList);
    }


}
